package com.party.admin.web.controller.article;

import com.alibaba.druid.sql.visitor.functions.Char;
import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Function;
import com.google.common.collect.Maps;
import com.party.admin.biz.article.ArticleBizService;
import com.party.admin.biz.file.FileBizService;
import com.party.core.utils.MyBeanUtils;
import com.party.admin.utils.RealmUtils;
import com.party.admin.web.dto.AjaxResult;
import com.party.admin.web.dto.input.common.CommonInput;
import com.party.admin.web.dto.output.article.ArticleOutput;
import com.party.common.paging.Page;
import com.party.common.utils.LangUtils;
import com.party.common.utils.StringUtils;
import com.party.core.model.BaseModel;
import com.party.core.model.article.Article;
import com.party.core.model.article.ArticleType;
import com.party.core.model.channel.Channel;
import com.party.core.model.subject.Subject;
import com.party.core.model.subject.SubjectApply;
import com.party.core.model.system.Dict;
import com.party.core.model.system.DictEnum;
import com.party.core.model.user.User;
import com.party.core.service.article.IArticleService;
import com.party.core.service.channel.IChannelService;
import com.party.core.service.cos.CosBizService;
import com.party.core.service.subject.ISubjectApplyService;
import com.party.core.service.subject.ISubjectService;
import com.party.core.service.system.IDictService;
import com.party.core.service.user.IUserService;
import org.apache.commons.lang3.StringEscapeUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import java.util.*;

/**
 * 文章
 *
 * @author Administrator
 *
 */
@Controller
@RequestMapping(value = "/article/article")
public class ArticleController {

	@Autowired
	private IArticleService articleService;

	@Autowired
	private IDictService dictService;

	@Autowired
	private IUserService userService;

	@Autowired
	private IChannelService channelService;

	@Autowired
	private FileBizService fileBizService;

	@Autowired
	private ISubjectApplyService subjectApplyService;

	@Autowired
	private ArticleBizService articleBizService;

	@Autowired
	private ISubjectService subjectService;

	@Autowired
	private CosBizService cosBizService;

	protected static Logger logger = LoggerFactory.getLogger(ArticleController.class);


	/**
	 * 文章管理
	 * @param article
	 * @param page
	 * @param commonInput
	 * @return
	 */
	@RequestMapping(value = "articleList")
	public ModelAndView articleList(Article article, Page page, CommonInput commonInput) {
		ModelAndView mv = new ModelAndView("article/articleList");

		if (article.getChannel() != null && StringUtils.isNotEmpty(article.getChannel().getId())) {
			mv.addObject("channelId", article.getChannel().getId());
		}

		article.setDelFlag(BaseModel.DEL_FLAG_NORMAL);
		Map<String, Object> params = CommonInput.appendParams(commonInput);
		//params.put("excludeType", ArticleType.ARTICLE_TYPE_SERVICE.getCode());

		mv.addObject("input", commonInput);

		if(StringUtils.isEmpty(article.getArticleType())){
			//过滤不需要的文章类型
			List<String> excludeTypes = new ArrayList<>();
			Map<String, String> stringStringMap = ArticleType.convertMap();
			for(Map.Entry<String, String> entry : stringStringMap.entrySet()){
				String mapKey = entry.getKey();
				String mapValue = entry.getValue();
				if(!(ArticleType.ARTICLE_TYPE_MATERIAL.getCode().equals(mapKey) ||
						ArticleType.ARTICLE_TYPE_SERVICE.getCode().equals(mapKey))){
					excludeTypes.add(mapKey);
				}
			}
			params.put("excludeTypes", excludeTypes);
		}


		List<Article> articles = articleService.webListPage(article, params, page);
		List<ArticleOutput> articleOutputs = LangUtils.transform(articles, input -> {
			input.setContent(null);
			ArticleOutput articleOutput = ArticleOutput.transform(input);
			String articleType = input.getArticleType();
			Dict dict = new Dict();
			dict.setDelFlag(BaseModel.DEL_FLAG_NORMAL);
			dict.setType(DictEnum.ARTICLE_TYPE.getCode());
			dict.setValue(articleType);
			Dict dictEntity = dictService.getByProperty(dict);
			if (dictEntity != null) {
				articleOutput.setArticleType(dictEntity.getLabel());
			}

			if (input.getChannel() != null) {
				Channel channel = channelService.get(input.getChannel().getId());
				articleOutput.setChannel(channel);
			}
			String filePath = fileBizService.getUploadCIPath(input.getMemberId(), "article");
			// 详情二维码
			String fileName = "detail_" + input.getId();
			String qrCodeUrl = cosBizService.getPreviewPictureUrl(filePath + fileName);
			articleOutput.setQrCodeUrl(qrCodeUrl);

			// 分销二维码
			String disFileName = "dis_" + input.getId();
			String disQrCodeUrl = cosBizService.getPreviewPictureUrl(filePath + disFileName);
			articleOutput.setDisQrCode(disQrCodeUrl);

			return articleOutput;
		});

		Dict dict = new Dict();
		dict.setType(DictEnum.ARTICLE_TYPE.getCode());
		mv.addObject("articleTypes", dictService.list(dict));

		mv.addObject("articles", articleOutputs);
		mv.addObject("page", page);
		return mv;
	}

	/**
	 * 从专题到发文章
	 * 
	 * @param id
	 * @return
	 */
	@RequestMapping(value = "articleForm")
	public ModelAndView publishArticle(String id, String applyId, String subjectId) {
		ModelAndView mv = new ModelAndView("article/articleForm");
		if (StringUtils.isNotEmpty(id)) {
			Article article = articleService.get(id);
			String content = StringUtils.unescapeHtml4Video2Iframe(article.getContent());
			article.setContent(content);
			mv.addObject("article", article);
		}

		Dict dict = new Dict();
		dict.setType(DictEnum.ARTICLE_TYPE.getCode());
		mv.addObject("types", dictService.list(dict));
		SubjectApply subjectApply = subjectApplyService.get(applyId);
		mv.addObject("subjectApply", subjectApply);
		if (subjectApply != null) {
			Subject subject = subjectService.get(subjectApply.getSubjectId());
			mv.addObject("subject", subject);
		}
		mv.addObject("subjectId", subjectId);
		return mv;
	}

	/**
	 * 直接发文章
	 * 
	 * @param id
	 * @param channelId
	 * @return
	 */
	@RequestMapping(value = "articleFormNormal")
	public ModelAndView articleFormNormal(String id, String channelId) {
		ModelAndView mv = new ModelAndView("article/articleForm");
		// 文章类型
		Dict dict = new Dict();
		dict.setType(DictEnum.ARTICLE_TYPE.getCode());
		mv.addObject("types", dictService.list(dict));
		// 频道
		if (StringUtils.isEmpty(channelId)) {
			Channel channel = new Channel();
			channel.setDelFlag(BaseModel.DEL_FLAG_NORMAL);
			List<Channel> channels = channelService.list(channel);
			mv.addObject("channels", channels);
		} else {
			Channel channel = channelService.get(channelId);
			mv.addObject("channel", channel);
		}
		// 文章
		if (StringUtils.isNotEmpty(id)) {
			Article article = articleService.get(id);
			String content = StringUtils.unescapeHtml4Video2Iframe(article.getContent());
			article.setContent(content);
			mv.addObject("article", article);
		}
		return mv;
	}

	/**
	 * 跳转至详情
	 * 
	 * @param id
	 * @return
	 */
	@RequestMapping(value = "articleDetail")
	public ModelAndView articleDetail(String id) {
		ModelAndView mv = new ModelAndView("article/articleDetail");
		Article article = articleService.get(id);
		if (StringUtils.isNotEmpty(article.getContent())) {
			article.setContent(StringUtils.unescapeHtml4Video2Iframe(article.getContent()));
		}
		String articleType = article.getArticleType();
		Dict dict = new Dict();
		dict.setDelFlag(BaseModel.DEL_FLAG_NORMAL);
		dict.setType(DictEnum.ARTICLE_TYPE.getCode());
		dict.setValue(articleType);
		Dict dictEntity = dictService.getByProperty(dict);
		if (dictEntity != null) {
			article.setArticleType(dictEntity.getLabel());
		}

		if (article.getChannel() != null) {
			Channel channel = channelService.get(article.getChannel().getId());
			article.setChannel(channel);
		}

		mv.addObject("article", article);
		return mv;
	}

	/**
	 * 三个入口：1直接发布文章 2从频道里面发布文章 3从文章组发布文章
	 * 
	 * @param article
	 * @param result
	 * @param channelId
	 *            不为空 表示从频道进来
	 * @param applyId
	 * @param subjectId
	 * @return
	 * @throws Exception
	 */
	@ResponseBody
	@RequestMapping(value = "save")
	public AjaxResult save(Article article, BindingResult result, String channelId, String applyId, String subjectId) throws Exception {
		try {
			AjaxResult ajaxResult = new AjaxResult();
			String memberId = RealmUtils.getCurrentUser().getId();
			// 数据验证
			if (result.hasErrors()) {
				List<ObjectError> allErros = result.getAllErrors();
				ajaxResult.setDescription(allErros.get(0).getDefaultMessage());
				return ajaxResult;
			}

			if (StringUtils.isNotEmpty(article.getContent())) {
				String content = StringUtils.escapeHtml4Iframe2Video(article.getContent().trim());
				article.setContent(content);
			}

			if (article.getReadNum() == null) {
				article.setReadNum(0);
			}

			SubjectApply apply = null;
			if (StringUtils.isNotEmpty(applyId)) {
				apply = subjectApplyService.get(applyId);
				if (apply.getType().equals("channel")) {
					article.setArticleGroupId(apply.getTargetId());
				}
			}

			if (StringUtils.isNotEmpty(article.getId())) {
				Article t = articleService.get(article.getId());
				MyBeanUtils.copyBeanNotNull2Bean(article, t);// 将编辑表单中的非NULL值覆盖数据库记录中的值
				if (StringUtils.isNotEmpty(article.getType())) {
					if (article.getType().equals("out")) {
						t.setContent("");
					} else if (article.getType().equals("local")) {
						t.setUrl("");
					}
				}
				articleService.update(t);
				memberId = t.getMemberId();
			} else {
				User user = userService.findByLoginName("admin");
				article.setCreateBy(user.getId());
				article.setUpdateBy(user.getId());
				article.setMemberId(memberId);
				if (StringUtils.isNotEmpty(channelId)) {
					Channel channel = channelService.get(channelId);
					article.setChannel(channel);
				}

				if (StringUtils.isNotEmpty(article.getType())) {
					article.setType("local");
				}

				String articleId = articleService.insert(article);

				if (apply != null && apply.getType().equals("article")) {
					apply.setUrl(SubjectApply.MIC_URL + "article/article_detail.html?id=" + articleId);
					apply.setTargetId(articleId);
					apply.setUpdateDate(new Date());
					subjectApplyService.update(apply);
				}
			}

			try {
				articleBizService.uploadQrCode(memberId, article.getId());
			} catch (Exception e) {
				logger.error("生成文章二维码异常", e);
			}

			Map<String, Object> map = new HashMap<String, Object>();
			if (StringUtils.isNotEmpty(channelId)) {
				map.put("channelId", channelId);
				ajaxResult.setData(map);
			}

			if (apply != null) {
				map.put("applyId", apply.getId());
				map.put("subjectId", apply.getSubjectId());
				ajaxResult.setData(map);
			}
			ajaxResult.setSuccess(true);
			return ajaxResult;
		} catch (Exception e) {
			logger.error("保存文章异常", e);
			return AjaxResult.error("保存文章异常");
		}
	}

	/**
	 * 读取频道下的文章
	 * 
	 * @param page
	 * @param channelId
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value = "getArticleByChanne")
	public Map<String, Object> publishListJson(Page page, String channelId) {
		Article article = new Article();
		Channel channel = new Channel();
		channel.setId(channelId);
		article.setChannel(channel);
		article.setDelFlag(BaseModel.DEL_FLAG_NORMAL);
		List<Article> articles = articleService.listPage(article, page);

		for (Article entity : articles) {
			String articleType = entity.getArticleType();
			Dict dict = new Dict();
			dict.setDelFlag(BaseModel.DEL_FLAG_NORMAL);
			dict.setType(DictEnum.ARTICLE_TYPE.getCode());
			dict.setValue(articleType);
			Dict dictEntity = dictService.getByProperty(dict);
			if (dictEntity != null) {
				entity.setArticleType(dictEntity.getLabel());
			}
		}
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("articles", articles);
		map.put("page", page);
		return map;
	}

	/**
	 * 删除文章
	 */
	@ResponseBody
	@RequestMapping(value = "delete")
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public AjaxResult delete(String id, String subjectId, String applyId) {
		if (StringUtils.isEmpty(id)) {
			return new AjaxResult(false);
		}

		boolean result = articleBizService.deleteArticleBiz(id);
		if (result) {
			if (StringUtils.isNotEmpty(applyId)) {
				SubjectApply subjectApply = subjectApplyService.get(applyId);
				if (subjectApply.getType().equals("article")) {
					subjectApply.setTargetId("");
					subjectApplyService.update(subjectApply);
				}
			}
			Map<String, Object> map = new HashMap<String, Object>();
			map.put("applyId", applyId);
			map.put("subjectId", subjectId);
			return AjaxResult.success(map);
		} else {
			return AjaxResult.error("删除失败");
		}
	}

	@ResponseBody
	@RequestMapping("initQrCode")
	public AjaxResult initQrCode() {
		List<Article> articles = articleService.list(new Article());
		for (Article article : articles) {
			String publisher = article.getMemberId();
			if (StringUtils.isEmpty(publisher)) {
				continue;
			}
			
			String filePath = fileBizService.getUploadCIPath(publisher, "article");

			String fileName = "detail_" + article.getId();
			String localFilePath = publisher + "/article/";
			String content = "article/article_detail.html?id=" + article.getId();
			fileBizService.uploadCloudOut(fileName, filePath, localFilePath, article.getId(), content, publisher);

			String disFileName = "dis_" + article.getId();
			String disLocalPath = publisher + "/distribution/";
			String disContent = articleBizService.getDistributionUrl(article.getId(), publisher);
			fileBizService.uploadCloudOut(disFileName, filePath, disLocalPath, article.getId(), disContent, publisher);
		}
		return AjaxResult.success();
	}

	@RequestMapping("selectArticle")
	public ModelAndView selectArticle(Article article, Page page) {
		page.setLimit(5);
		article.setDelFlag(BaseModel.DEL_FLAG_NORMAL);
		List<Article> articles = articleService.listPage(article, page);
		List<Map<String, Object>> mapList = LangUtils.transform(articles, new Function<Article, Map<String, Object>>() {
			@Override
			public Map<String, Object> apply(Article input) {
				Map<String, Object> map = Maps.newHashMap();
				map.put("targetId", input.getId());
				map.put("targetName", input.getTitle());
				return map;
			}
		});
		ModelAndView mv = new ModelAndView("gift/selectProject");
		mv.addObject("mapList", mapList);
		mv.addObject("page", page);
		mv.addObject("requestUrl", "article/article/selectArticle.do");
		mv.addObject("mapSearch", article);
		return mv;
	}


	/**
	 * 拖曳更新排序
	 * @param jsonStr 排序json字符串
	 * @return
	 */
	@ResponseBody
	@RequestMapping("dragUpdateSort")
	public AjaxResult dragUpdateSort(String jsonStr) {
		if (StringUtils.isEmpty(jsonStr)) {
			return AjaxResult.error("文章排序json字符串不能为空");
		}
		Map<String, Integer> resultMap = JSONObject.parseObject(jsonStr, Map.class);
		for (Map.Entry<String, Integer> result : resultMap.entrySet()) {
			String articleId = result.getKey(); // 文章id
			Integer newSort = result.getValue(); // 排序号
			Article article = articleService.get(articleId);
			article.setSort(newSort);
			articleService.update(article);
		}
		return AjaxResult.success();
	}

	@ResponseBody
	@RequestMapping("upDownUpdateSort")
	public AjaxResult upDownUpdateSort(String articleId, String type, String applyId) {
		if (StringUtils.isEmpty(type)) {
			return AjaxResult.error("操作类型不能为空");
		}
		if (StringUtils.isEmpty(articleId)) {
			return AjaxResult.error("文章id不能为空");
		}
		try {
			SubjectApply subjectApply = subjectApplyService.get(applyId);
			Article t = new Article();
			t.setArticleGroupId(subjectApply.getTargetId());//targetId:文章id或者文章组id
			List<Article> articles = articleService.list(t);
			Collections.sort(articles, new Comparator<Article>() {
				@Override
				public int compare(Article o1, Article o2) {
					if (null == o1.getSort()) return 1;
					if (null == o2.getSort()) return 1;
					return o1.getSort() >= o2.getSort() ? 1 : - 1;
				}
			});

			for (int i = 0; i < articles.size(); i++) {
				Article entity = articles.get(i);
				if (null == entity.getSort()) {
					entity.setSort(articles.size());
					articleService.update(entity);
				}
				if (entity.getId().equals(articleId)) {
					if ("up".equals(type)) {
						if (i - 1 > 0) {
							Article before = articles.get(i - 1);
							before.setSort(before.getSort() + 1);
							articleService.update(before);
						}
						break;
					} else if ("down".equals(type)) {
						if (i + 1 < articles.size()) {
							Article after = articles.get(i + 1);
							after.setSort(after.getSort() - 1);
							articleService.update(after);
						}
						break;
					}
				}
			}

			Article article = articleService.get(articleId);
			if ("up".equals(type)) {
				if (article.getSort() == 1) {
					return AjaxResult.error("已经是第一位了");
				}
				article.setSort(article.getSort() - 1);
			} else if ("down".equals(type)) {
				article.setSort(article.getSort() + 1);
			}
			articleService.update(article);
			return AjaxResult.success();
		} catch (Exception e) {
			logger.error("更新排序异常", e);
			return AjaxResult.error("更新排序异常");
		}
	}
}
